#其 中梯度提升模型（Gradient Boosting）的表现是最好的

"""
每个列名的解释：
    survived: 是否存活（0 = No, 1 = Yes）
    pclass: 舱位等级（1 = 1st, 2 = 2nd, 3 = 3rd）
    sex: 性别（male 或 female）
    age: 年龄
    sibsp: 兄弟姐妹/配偶的数量
    parch: 父母/子女的数量
    fare: 票价
    embarked: 登船港口（C = Cherbourg, Q = Queenstown, S = Southampton）
    class: 舱位等级（与 pclass 类似）
    who: 乘客类型（man, woman, child）
    adult_male: 是否成年男性（True 或 False）
    deck: 甲板等级
    embark_town: 登船城市
    alone: 是否独自一人（True 或 False）
    alive: 是否存活（yes 或 no）
"""

"""
数据分析：
    survived: 这是我们的目标变量，表示乘客是否存活。
    pclass: 乘客的舱位等级，可能与存活率有很大关系。
    sex: 性别，通常女性的存活率较高。
    age: 年龄，可能需要处理缺失值，并且可以创建年龄段特征。
    sibsp: 兄弟姐妹/配偶的数量，可能影响存活率。
    parch: 父母/子女的数量，可能影响存活率。
    fare: 票价，可能与舱位等级和存活率相关。
    embarked: 登船港口，可能需要处理缺失值。
    class: 与 pclass 类似，可能是重复信息。
    who: 乘客类型，可能与性别和年龄相关。
    adult_male: 是否成年男性，可能与性别和年龄相关。
    deck: 甲板等级，可能需要处理缺失值。
    embark_town: 登船城市，可能与 embarked 重复。
    alone: 是否独自一人，可能与 sibsp 和 parch 相关。
    alive: 与 survived 类似，可能是重复信息。
"""


import pandas as pd
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.svm import SVC
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix, roc_curve, auc, roc_auc_score
import seaborn as sns

# Step 1: 导入数据
train_df = pd.read_csv('titanic.csv')
test_df = pd.read_csv('view.csv')

# Step 2: 数据预处理
# 检查数据框的列名
print("Train dataset columns:", train_df.columns)
print("Test dataset columns:", test_df.columns)

# 去掉不需要的字段，比如 'class', 'who', 'deck', 'embark_town', 'alive'
unused_columns = ['class', 'who', 'deck', 'embark_town', 'alive']
train_df.drop(columns=unused_columns, inplace=True)
test_df.drop(columns=unused_columns, inplace=True)

# 填充缺失值
train_df['age'] = train_df['age'].fillna(train_df['age'].median())
test_df['age'] = test_df['age'].fillna(test_df['age'].median())
train_df['embarked'] = train_df['embarked'].fillna(train_df['embarked'].mode()[0])
test_df['embarked'] = test_df['embarked'].fillna(test_df['embarked'].mode()[0])
test_df['fare'] = test_df['fare'].fillna(test_df['fare'].median())

# 转换分类变量为数值
le = LabelEncoder()
train_df['sex'] = le.fit_transform(train_df['sex'])
test_df['sex'] = le.transform(test_df['sex'])
train_df['embarked'] = le.fit_transform(train_df['embarked'])
test_df['embarked'] = le.transform(test_df['embarked'])

# 分割特征和标签
X = train_df.drop('survived', axis=1)
y = train_df['survived']

# 确保 test_df 不包含 'survived' 列
X_test = test_df.drop('survived', axis=1)

# 训练集和测试集分割
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)

# 特征标准化
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_val = scaler.transform(X_val)
X_test = scaler.transform(X_test)  # 保持特征一致性

# Step 3: 训练模型
# 训练随机森林模型
rf = RandomForestClassifier(random_state=42)
rf.fit(X_train, y_train)
y_pred_rf = rf.predict(X_val)
print("Random Forest Accuracy: ", accuracy_score(y_val, y_pred_rf))
print(classification_report(y_val, y_pred_rf))

# 训练逻辑回归模型
lr = LogisticRegression(random_state=42)
lr.fit(X_train, y_train)
y_pred_lr = lr.predict(X_val)
print("Logistic Regression Accuracy: ", accuracy_score(y_val, y_pred_lr))
print(classification_report(y_val, y_pred_lr))

# 训练支持向量机模型
svc = SVC(random_state=42)
svc.fit(X_train, y_train)
y_pred_svc = svc.predict(X_val)
print("SVM Accuracy: ", accuracy_score(y_val, y_pred_svc))
print(classification_report(y_val, y_pred_svc))

# 训练梯度提升模型
gb = GradientBoostingClassifier(random_state=42)
gb.fit(X_train, y_train)
y_pred_gb = gb.predict(X_val)
print("Gradient Boosting Accuracy: ", accuracy_score(y_val, y_pred_gb))
print(classification_report(y_val, y_pred_gb))

# 步骤 4: 使用最优模型进行预测（假设梯度提升表现最好）
final_predictions = gb.predict(X_test)

# 生成预测结果的DataFrame
output_df = pd.DataFrame(
    {'PassengerId': test_df.index + 1, 'Survived': final_predictions})  # 假设 PassengerId 是 index，从1开始

# 导出结果
output_df.to_csv('submission.csv', index=False)

# Step 5: 模型性能可视化
# 计算混淆矩阵
cm_rf = confusion_matrix(y_val, y_pred_rf)
cm_lr = confusion_matrix(y_val, y_pred_lr)
cm_svc = confusion_matrix(y_val, y_pred_svc)
cm_gb = confusion_matrix(y_val, y_pred_gb)

# 绘制混淆矩阵
fig, axes = plt.subplots(2, 2, figsize=(12, 12))
sns.heatmap(cm_rf, annot=True, fmt="d", cmap="Blues", ax=axes[0, 0]).set_title('Random Forest Confusion Matrix')
sns.heatmap(cm_lr, annot=True, fmt="d", cmap="Blues", ax=axes[0, 1]).set_title('Logistic Regression Confusion Matrix')
sns.heatmap(cm_svc, annot=True, fmt="d", cmap="Blues", ax=axes[1, 0]).set_title('SVM Confusion Matrix')
sns.heatmap(cm_gb, annot=True, fmt="d", cmap="Blues", ax=axes[1, 1]).set_title('Gradient Boosting Confusion Matrix')
plt.show()

# 计算ROC曲线和AUC值
fpr_rf, tpr_rf, _ = roc_curve(y_val, rf.predict_proba(X_val)[:, 1])
fpr_lr, tpr_lr, _ = roc_curve(y_val, lr.predict_proba(X_val)[:, 1])
fpr_svc, tpr_svc, _ = roc_curve(y_val, svc.decision_function(X_val))
fpr_gb, tpr_gb, _ = roc_curve(y_val, gb.predict_proba(X_val)[:, 1])

roc_auc_rf = roc_auc_score(y_val, rf.predict_proba(X_val)[:, 1])
roc_auc_lr = roc_auc_score(y_val, lr.predict_proba(X_val)[:, 1])
roc_auc_svc = roc_auc_score(y_val, svc.decision_function(X_val))
roc_auc_gb = roc_auc_score(y_val, gb.predict_proba(X_val)[:, 1])

# 绘制ROC曲线
plt.figure(figsize=(10, 8))
plt.plot(fpr_rf, tpr_rf, label=f'Random Forest (AUC = {roc_auc_rf:.2f})')
plt.plot(fpr_lr, tpr_lr, label=f'Logistic Regression (AUC = {roc_auc_lr:.2f})')
plt.plot(fpr_svc, tpr_svc, label=f'SVM (AUC = {roc_auc_svc:.2f})')
plt.plot(fpr_gb, tpr_gb, label=f'Gradient Boosting (AUC = {roc_auc_gb:.2f})')
plt.plot([0, 1], [0, 1], 'k--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.legend(loc='lower right')
plt.show()
